package com.company.graph;

import com.company.graphgetter.NodeGetterWithGraph;

import java.util.*;

public class NopowerNoDirectNodeGraph implements NodeGraph {
    private HashMap<Integer, HashSet<Integer>> adjs;
    private Integer edgeTotal = 0;

    public NopowerNoDirectNodeGraph() {
        adjs = new HashMap<>();
    }

    public void addEdge(int v, int w) {
        if (v == w) {
            return;
        }
        Set<Integer> vSet, wSet;
        vSet = getSetById(v);
        wSet = getSetById(w);
        vSet.add(w);
        wSet.add(v);
    }

    @Override
    public void addEdge(int v, int w, double power) {
        this.addEdge(v, w);
    }

    public void deleteEdge(int v, int w) {
        Set<Integer> vSet, wSet;
        vSet = getSetById(v);
        wSet = getSetById(w);
        vSet.remove(w);
        wSet.remove(v);
    }

    @Override
    public String display() {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Integer, HashSet<Integer>> entry : adjs.entrySet()) {
            Integer v = entry.getKey();
            sb.append(v);
            sb.append(' ');
            HashSet<Integer> wSet = entry.getValue();
            for (Integer w : wSet) {
                sb.append(w);
                sb.append(' ');
            }
            sb.append('\n');
        }
        return sb.toString();
    }

    @Override
    public Integer E() {
        return edgeTotal;
    }

    public void deleteEdgeWithTriangle(int v, int w, NodeGetterWithGraph getFromGraph) {
        deleteEdge(v, w);
        getFromGraph.refreshPartialTriangle(v, w);
    }


    private HashSet<Integer> getSetById(int id) {
        HashSet<Integer> list;
        if (adjs.containsKey(id)) {
            list = adjs.get(id);
        } else {
            list = new HashSet<>();
            adjs.put(id, list);
        }
        return list;
    }

    @Override
    public String toString() {
        Set<Map.Entry<Integer, HashSet<Integer>>> entries = adjs.entrySet();
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Integer, HashSet<Integer>> entry : entries) {
            String str = "Node:" + entry.getKey() + "\n";
            sb.append(str);
            HashSet<Integer> neibors = entry.getValue();
            for (Integer w : neibors) {
                sb.append(w);
                sb.append(' ');
            }
            sb.append("\n--------\n");
        }
        return sb.toString();
    }

    public HashSet<Integer> adj(Integer w) {
        return adjs.get(w);
    }

    @Override
    public boolean hasEdge(Integer v, Integer w) {
        return adjs.get(v).contains(w);
    }

    @Override
    public int nodeLength() {
        return adjs.size();
    }

    public HashMap<Integer, HashSet<Integer>> adjs() {
        return adjs;
    }

    public int maxDegreeVertexById(int v) {
        int answer = -1;
        int recordDegree = 0;
        for (Integer w : adjs.get(v)) {
            int degree = adjs.get(w).size();
            if (degree > recordDegree) {
                recordDegree = degree;
                answer = w;
            }
        }
        return answer;
    }

}
